﻿using ConsoleHoster.Model.Suggestions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;

namespace ConsoleHoster.UnitTests.ModelTests.SuggestionsTests
{
	[TestClass]
	public class PathSuggestionContextTests
	{
		private Mock<IPathSuggestionProvider> mockPathSuggestionProvider;
		private PathSuggestionContext suggestionContext;

		[TestInitialize]
		public void Initialize()
		{
			this.mockPathSuggestionProvider = new Mock<IPathSuggestionProvider>();
			this.suggestionContext = new PathSuggestionContext(this.mockPathSuggestionProvider.Object);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Constructor_ThrowsExceptionForNullProvider()
		{
			new PathSuggestionContext(null);
		}

		[TestMethod]
		public void GetNextSuggestion_RetrievesNextSuggestionFromUnderlyingProvider()
		{
			const string tmpResult = "Windows";

			this.mockPathSuggestionProvider.Setup(p => p.GetNextSuggestion()).Returns(tmpResult);

			string tmpActualSuggestion = this.suggestionContext.GetNextSuggestion();

			Assert.AreEqual(tmpResult, tmpActualSuggestion);
		}

		[TestMethod]
		public void GetPreviousSuggestion_RetrievesPreviousSuggestionFromUnderlyingProvider()
		{
			const string tmpResult = "Windows";
			this.mockPathSuggestionProvider.Setup(p => p.GetPreviousSuggestion()).Returns(tmpResult);

			string tmpActual = this.suggestionContext.GetPreviousSuggestion();

			Assert.AreEqual(tmpResult, tmpActual);
		}

		[TestMethod]
		public void UpdateContext_SetsTheLastProvidedSuggestionToPassedInBase()
		{
			const string tmpPattern = "SomeBaseString";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", tmpPattern), "C:\\");

			Assert.AreEqual(tmpPattern, this.suggestionContext.LastProvidedSuggestion);
		}

		[TestMethod]
		public void UpdateContext_PreparesSuggestionsOnUnderlyingProvider()
		{
			string argFolder = "C:\\windows\\";
			string argPattern = "SomeBaseString";

			Assert.IsTrue(this.suggestionContext.UpdateContext(String.Format("{0}{1}\t", argFolder, argPattern), "D:\\"));

			this.mockPathSuggestionProvider.Verify(p => p.PrepareSuggestions(argFolder, argPattern, false), Times.Once());
		}

		[TestMethod]
		public void UpdateContext_ReturnsTrueInCaseOfCorrectInput()
		{
			const string tmpCommand = "some command in here C:\\Windows\\a";
			const string tmpCurrentFolder = "C:\\Windows\\";

			Assert.IsTrue(this.suggestionContext.UpdateContext(String.Format("{0}\t", tmpCommand), tmpCurrentFolder));
		}

		[TestMethod]
		public void UpdateContext_PreparesSuggestionsWhenSuggestionIsPrefixedWithFullPath()
		{
			const string tmpCommandFullPath = "C:\\Programs\\";
			const string tmpCommand = "some command in here {0}a";
			const string tmpCurrentFolder = "C:\\Windows\\";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", String.Format(tmpCommand, tmpCommandFullPath)), tmpCurrentFolder);

			this.mockPathSuggestionProvider.Verify(p => p.PrepareSuggestions(tmpCommandFullPath, "a", false), Times.Once());
		}

		[TestMethod]
		public void UpdateContext_PreparesSuggestionsWhenSuggestionIsPrefixedWithRelativePath()
		{
			const string tmpCommandRelativePath = "../../Install/";
			const string tmpCommand = "some command in here {0}a";
			const string tmpCurrentFolder = "C:\\Windows\\";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", String.Format(tmpCommand, tmpCommandRelativePath)), tmpCurrentFolder);

			this.mockPathSuggestionProvider.Verify(p => p.PrepareSuggestions(tmpCurrentFolder + tmpCommandRelativePath, "a", false), Times.Once());
		}

		[TestMethod]
		public void UpdateContext_PreparesSuggestionsWhenSuggestionIsPrefixedWithRelativePathWithoutPattern()
		{
			const string tmpCommandRelativePath = "Windows/";
			const string tmpCommand = "cd {0}";
			const string tmpCurrentFolder = "C:\\";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", String.Format(tmpCommand, tmpCommandRelativePath)), tmpCurrentFolder);

			this.mockPathSuggestionProvider.Verify(p => p.PrepareSuggestions(tmpCurrentFolder + tmpCommandRelativePath, "", true), Times.Once());
		}

		[TestMethod]
		public void UpdateContext_ReturnsTrueIfNotReset()
		{
			const string tmpCommandRelativePath = "Windows/";
			const string tmpCommand = "cd {0}";
			const string tmpCurrentFolder = "C:\\";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", String.Format(tmpCommand, tmpCommandRelativePath)), tmpCurrentFolder);

			Assert.IsTrue(this.suggestionContext.UpdateContext("cmd", "d:"));
		}

		[TestMethod]
		public void Reset_ResetsSavedState()
		{
			const string tmpCommandRelativePath = "Windows/";
			const string tmpCommand = "cd {0}";
			const string tmpCurrentFolder = "C:\\";

			this.suggestionContext.UpdateContext(String.Format("{0}\t", String.Format(tmpCommand, tmpCommandRelativePath)), tmpCurrentFolder);

			Assert.IsNotNull(this.suggestionContext.LastProvidedSuggestion);
			Assert.IsNotNull(this.suggestionContext.Pattern);

			this.suggestionContext.Reset();

			Assert.IsNull(this.suggestionContext.LastProvidedSuggestion);
			Assert.IsNull(this.suggestionContext.Pattern);
		}
	}
}
